# 导入所需的调度器类和触发器类
from apscheduler.schedulers.background import BackgroundScheduler #后台运行
from apscheduler.schedulers.blocking import BlockingScheduler  #主进程运行，需要单独运行
from apscheduler.triggers.interval import IntervalTrigger #时间间隔
from apscheduler.triggers.cron import CronTrigger #复杂的定时任务
from apscheduler.triggers.date import DateTrigger #一次性定时任务
from apscheduler import events
from datetime import datetime
#定时任务
from .task import delete_apscheduler_history
from .task import send_to_big_data
from .task import crontab_task,date_task
#日志
from .config import LISTENER
from .config import TIME_ZONE,JOB_DEFAULTS,JOB_STORE,Scheduler_Logger #调度器配置

class TheBlockScheduler(object):
    TIME_FORMAT = '%Y-%m-%d %H:%M:%S'
    def __init__(self):
        self.scheduler = self._scheduler_obj()
        self.logger = Scheduler_Logger.get('logger')
    # 1、初始化调度器
    def _scheduler_obj(self):
        obj = BlockingScheduler()
        obj.configure(
            timezone=TIME_ZONE,  # 时区
            job_defaults=JOB_DEFAULTS,  # job的默认配置
            jobstores=JOB_STORE,  # job的存储后端
            gconfig=Scheduler_Logger, #日志记录相关的的配置
        )
        return obj

    # 2、添加任务
    def _add_job(self):
        # 每5分钟执行一次推送告警到大数据仓
        self.scheduler.add_job(
            send_to_big_data,
            trigger=IntervalTrigger(minutes=1),
            id='send_to_big_data',
            replace_existing=True,
            coalesce=True,
            name='该定时，用于将数据推送到远端大数据系统'
        )

        # 每天凌晨，清除历史的记录
        self.scheduler.add_job(
            delete_apscheduler_history,
            trigger=CronTrigger(hour=0,minute=0,second=1),
            id='delete_apscheduler_history',
            replace_existing=True,
            coalesce=True,
            name='该定时器，是将历史定时任务的执行记录进行清除'
        )

        # 每隔20分钟清除垃圾记录
        self.scheduler.add_job(
            crontab_task,
            trigger=IntervalTrigger(minutes=20),  # 每天晚上零点1秒执行
            id='crontab_task',
            replace_existing=True,
            coalesce=True,
            name='该定时任务，用于清除xxx表中的垃圾记录'
        )

        #在指定某个时刻执行一次
        self.scheduler.add_job(
            date_task,
            trigger=DateTrigger(run_date='2024-12-03 10:11:30'),
            id='date_task',
            replace_existing=True,
            coalesce=True,
            name='该定时任务，在指定时间，进行系统初始化任务',
        )

    # 3、添加监听器
    def _listener(self, event: events):
        code = event.code
        run_time = datetime.now().strftime(self.TIME_FORMAT)
        msg = LISTENER.get(code)
        #存储器
        jobstore = self.scheduler._jobstores['default']
        job_history_data = {
            'job_id':None,
            'run_time':None,
            'is_error':0,
            'error_msg':None
        }

        if code == 4096:
            # 成功运行
            job_id = event.job_id
            job_history_data['job_id'] = job_id
            job_history_data['run_time'] = run_time
            # 记录到数据库中
            jobstore.insert_job_history(job_history_data)
        elif code == 8192 or code == 16384:
            # 运行异常了
            job_id = event.job_id
            job_history_data['job_id'] = job_id
            job_history_data['run_time'] = run_time
            job_history_data['is_error'] = 1
            job_history_data['error_msg'] = msg
            # 记录到数据库中
            jobstore.insert_job_history(job_history_data)
        elif code in (1,2,4,8,32,128,1024,2048):
            ###调度器启动时
            self.logger.info(msg)
            try:
                job_id = event.job_id
                if msg:
                    msg = '任务id={}，{}'.format(job_id, msg)
                    self.logger.info(msg)
            except Exception:
                if msg:
                    self.logger.info(msg)
    # 4、启动定时器
    def start(self):
        # 1、设置定时任务(监听器会先监听到任务添加，再监听到调度器启动)
        self._add_job()
        # 2、设置监听器
        self.scheduler.add_listener(self._listener)
        # 3、启动调度器
        try:
            # print('{},定时器启动成功,等待定时任务执行...'.format(datetime.now().strftime(self.TIME_FORMAT)))
            self.scheduler.start()
        except KeyboardInterrupt:
            self.scheduler.shutdown()

#后台线程运行：随django项目一起运行
class TheBackRunScheduler(TheBlockScheduler):
    def _scheduler_obj(self):
        obj = BackgroundScheduler()
        obj.configure(
            timezone=TIME_ZONE,  # 时区
            job_defaults=JOB_DEFAULTS,  # job的默认配置
            jobstores=JOB_STORE,  # job的存储后端
            gconfig=Scheduler_Logger,  # 日志记录相关的的配置
        )
        return obj



if __name__ == '__main__':
    #后台启动
    backScheduler = TheBackRunScheduler()
    backScheduler.start()